package com.cskaoyan.config;

import com.cskaoyan.config.realm.CustomRealm;
import lombok.Data;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.LinkedHashMap;

/**
 * @Auther: Yang Yi-zhou
 * @Date: 2022/9/8 15:21
 * @Description:
 */
@Configuration
@Data
public class ShiroConfig {

    @Autowired
    HashProperties hashProperties;

//    private final static Integer HASH_ITERATIONS = 2;

    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
//        hashedCredentialsMatcher.setHashIterations(HASH_ITERATIONS);
        hashedCredentialsMatcher.setHashIterations(hashProperties.getTimes());
        return hashedCredentialsMatcher;
    }

    @Bean
    public CustomRealm customRealm(HashedCredentialsMatcher hashedCredentialsMatcher) {
        CustomRealm customRealm = new CustomRealm();
        customRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return customRealm;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 配置SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 配置Filter链 key -> url, value -> anon, authc, perms
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //这里注意anon, authc, perms等value是shiro内置的，不能写错
        filterChainDefinitionMap.put("/admin/auth/login", "anon");
        filterChainDefinitionMap.put("/admin/auth/info", "anon");
        filterChainDefinitionMap.put("/admin/auth/logout", "anon");
//        filterChainDefinitionMap.put("/admin/auth/noAuthc", "anon");
        filterChainDefinitionMap.put("/admin/**", "authc");
        //除了put的方式，还可以使用aspectj来使用注解进行耦合，只需要再对应handler方法上增加@RequiresPermissions("[指定的权限]")即可完成同样的功能

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        // 认证失败，Shiro会把请求 重定向到这个url
//        shiroFilterFactoryBean.setLoginUrl("admin/auth/login");

        return shiroFilterFactoryBean;
    }


    @Bean
    public DefaultWebSecurityManager securityManager(CustomRealm customRealm, SessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 配置Realms和SessionManager
        securityManager.setRealms(Arrays.asList(customRealm));
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }

    @Bean
    public DefaultWebSessionManager sessionManager() {
//        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        //改用自定义的SessionManager
        DefaultWebSessionManager sessionManager = new CustomSessionManager();
        return sessionManager;
    }


    // 注册一个advisor来支持aspectj实现通过注解来实现Shirofilter和handler方法的耦合
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        // 需要给advisor配置securityManager依赖
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }




}
